﻿package core.image.encoder
{
    import core.enum.*;
    import core.image.*;
    import flash.display.*;
    import flash.filters.*;
    import flash.text.*;
    import flash.utils.*;

    public class TUDEncoder extends Object
    {
        public const version:int = 3;

        public function TUDEncoder()
        {
            return;
        }// end function

        public function encode(param1:Document) : ByteArray
        {
            var _loc_2:Layer = null;
            var _loc_3:int = 0;
            var _loc_4:ByteArray = null;
            var _loc_5:* = new ByteArray();
            var _loc_6:* = this.WriteHeader(_loc_5, param1);
            while (_loc_3 < param1.numChildren)
            {
                
                _loc_2 = param1.getChildAt(_loc_3) as Layer;
                _loc_4 = this.WriteLayer(_loc_2, param1);
                _loc_5.writeUnsignedInt(_loc_4.length);
                _loc_5.writeBytes(_loc_4);
                _loc_3++;
            }
            this.WriteLocationOfFlattened(_loc_5, _loc_5.length);
            this.WriteFlattened(_loc_5, param1);
            _loc_5.compress();
            return _loc_5;
        }// end function

        private function WriteHeader(writeBytes:ByteArray, writeBytes:Document) : void
        {
            writeBytes.writeShort(this.version);
            writeBytes.writeShort(0);
            writeBytes.writeInt(writeBytes.dw);
            writeBytes.writeInt(writeBytes.dh);
            writeBytes.writeShort(writeBytes.numChildren);
            writeBytes.writeUnsignedInt(0);
            return;
        }// end function

        private function WriteLocationOfFlattened(writeBytes:ByteArray, writeBytes:uint) : void
        {
            writeBytes.position = 14;
            writeBytes.writeUnsignedInt(writeBytes.length);
            writeBytes.position = writeBytes;
            return;
        }// end function

        private function WriteFlattened(writeBytes:ByteArray, writeBytes:Document) : void
        {
            var _loc_3:* = new BitmapData(writeBytes.dw, writeBytes.dh, true, 16777215);
            _loc_3.draw(writeBytes);
            var _loc_4:* = _loc_3.getPixels(_loc_3.rect);
            writeBytes.writeBytes(_loc_4);
            return;
        }// end function

        private function WriteLayer(param1:Layer, param2:Document) : ByteArray
        {
            var _loc_3:ByteArray = null;
            var _loc_4:* = new ByteArray();
            _loc_4.writeUTF(param1.name);
            _loc_4.writeByte(this.LayerTypeToInt(param1.type));
            _loc_4.writeInt(param1.x);
            _loc_4.writeInt(param1.y);
            if (param1.type == LayerType.Text)
            {
                param1.bitmap = new Bitmap(new BitmapData(param1.width, param1.height, true, 16777215));
                param1.bitmap.bitmapData.draw(param1.text);
            }
            _loc_4.writeInt(param1.width);
            _loc_4.writeInt(param1.height);
            _loc_4.writeByte(int(param1.alpha * 100));
            _loc_4.writeBoolean(param1.visible);
            _loc_4.writeByte(this.BlendModeToInt(param1.blendMode));
            _loc_4.writeBoolean(param1.alphaLock);
            if (param1.bitmap != null && param1.bitmap.bitmapData != null)
            {
                _loc_3 = param1.bitmap.bitmapData.getPixels(param1.bitmap.bitmapData.rect);
                _loc_4.writeUnsignedInt(_loc_3.length);
                _loc_4.writeBytes(_loc_3);
            }
            else
            {
                _loc_4.writeUnsignedInt(0);
            }
            this.WriteLayerMask(_loc_4, param1);
            this.WriteLayerStyle(_loc_4, param1);
            this.WriteLayerResources(_loc_4, param1);
            return _loc_4;
        }// end function

        private function WriteLayerMask(writeBytes:ByteArray, writeBytes:Layer) : void
        {
            var _loc_3:ByteArray = null;
            if (writeBytes.hasMask && writeBytes.masking.bitmapData != null)
            {
                _loc_3 = writeBytes.masking.bitmapData.getPixels(writeBytes.masking.bitmapData.rect);
                writeBytes.writeUnsignedInt(_loc_3.length);
                writeBytes.writeBytes(_loc_3);
            }
            else
            {
                writeBytes.writeUnsignedInt(0);
            }
            return;
        }// end function

        private function WriteLayerStyle(writeBytes:ByteArray, writeBytes:Layer) : void
        {
            var _loc_3:int = 0;
            var _loc_4:ByteArray = null;
            writeBytes.writeByte(writeBytes.filters.length);
            while (_loc_3 < writeBytes.filters.length)
            {
                
                if (writeBytes.filters[_loc_3] is DropShadowFilter && (writeBytes.filters[_loc_3] as DropShadowFilter).inner)
                {
                    _loc_4 = this.WriteShadow(writeBytes.filters[_loc_3], 101);
                }
                else if (writeBytes.filters[_loc_3] is DropShadowFilter && !(writeBytes.filters[_loc_3] as DropShadowFilter).inner)
                {
                    _loc_4 = this.WriteShadow(writeBytes.filters[_loc_3], 102);
                }
                else if (writeBytes.filters[_loc_3] is BevelFilter)
                {
                    _loc_4 = this.WriteBevel(writeBytes.filters[_loc_3]);
                }
                else if (writeBytes.filters[_loc_3] is GlowFilter && (writeBytes.filters[_loc_3] as GlowFilter).inner)
                {
                    _loc_4 = this.WriteGlow(writeBytes.filters[_loc_3], 104);
                }
                else if (writeBytes.filters[_loc_3] is GlowFilter && !(writeBytes.filters[_loc_3] as GlowFilter).inner)
                {
                    _loc_4 = this.WriteGlow(writeBytes.filters[_loc_3], 105);
                }
                writeBytes.writeUnsignedInt(_loc_4.length);
                writeBytes.writeBytes(_loc_4);
                _loc_3++;
            }
            return;
        }// end function

        private function WriteLayerResources(writeBytes:ByteArray, writeBytes:Layer) : void
        {
            var _loc_3:ByteArray = null;
            if (writeBytes.type == LayerType.Text)
            {
                writeBytes.writeShort(1);
                _loc_3 = this.WriteText(writeBytes);
                writeBytes.writeUnsignedInt(_loc_3.length);
                writeBytes.writeBytes(_loc_3);
            }
            else
            {
                writeBytes.writeShort(0);
            }
            return;
        }// end function

        private function WriteText(param1:Layer) : ByteArray
        {
            var _loc_2:* = new ByteArray();
            var _loc_3:* = param1.text.getTextFormat();
            _loc_2.writeByte(101);
            _loc_2.writeUTF(param1.text.text);
            _loc_2.writeUTF(_loc_3.font);
            _loc_2.writeShort(_loc_3.size as int);
            _loc_2.writeUnsignedInt(_loc_3.color as uint);
            _loc_2.writeByte(0);
            _loc_2.writeShort(0);
            _loc_2.writeShort(0);
            _loc_2.writeBoolean(_loc_3.bold);
            _loc_2.writeBoolean(_loc_3.italic);
            _loc_2.writeBoolean(_loc_3.underline);
            return _loc_2;
        }// end function

        private function WriteShadow(param1:DropShadowFilter, param2:int) : ByteArray
        {
            var _loc_3:* = new ByteArray();
            _loc_3.writeByte(param2);
            _loc_3.writeByte(param1.alpha * 100);
            _loc_3.writeShort(param1.distance);
            _loc_3.writeByte(param1.blurX);
            _loc_3.writeShort(param1.angle);
            _loc_3.writeUnsignedInt(param1.color);
            return _loc_3;
        }// end function

        private function WriteBevel(param1:BevelFilter) : ByteArray
        {
            var _loc_2:* = new ByteArray();
            _loc_2.writeByte(103);
            _loc_2.writeByte(this.BevelStyleToInt(param1.type));
            _loc_2.writeShort(param1.distance);
            _loc_2.writeByte(param1.blurX);
            _loc_2.writeShort(param1.angle);
            _loc_2.writeByte(param1.highlightAlpha * 100);
            _loc_2.writeUnsignedInt(param1.highlightColor);
            _loc_2.writeByte(param1.shadowAlpha * 100);
            _loc_2.writeUnsignedInt(param1.shadowColor);
            return _loc_2;
        }// end function

        private function WriteGlow(param1:GlowFilter, param2:int) : ByteArray
        {
            var _loc_3:* = new ByteArray();
            _loc_3.writeByte(param2);
            _loc_3.writeByte(param1.alpha * 100);
            _loc_3.writeShort(param1.strength);
            _loc_3.writeByte(param1.blurX);
            _loc_3.writeUnsignedInt(param1.color);
            return _loc_3;
        }// end function

        private function BevelStyleToInt(getPixels:String) : int
        {
            switch(getPixels)
            {
                case "inner":
                {
                    return 0;
                }
                case "outer":
                {
                    return 1;
                }
                case "full":
                {
                    return 2;
                }
                default:
                {
                    return 0;
                    break;
                }
            }
        }// end function

        private function BlendModeToInt(getPixels:String) : int
        {
            switch(getPixels)
            {
                case "normal":
                {
                    return 0;
                }
                case "add":
                {
                    return 1;
                }
                case "alpha":
                {
                    return 2;
                }
                case "darken":
                {
                    return 3;
                }
                case "difference":
                {
                    return 4;
                }
                case "erase":
                {
                    return 5;
                }
                case "hardlight":
                {
                    return 6;
                }
                case "invert":
                {
                    return 7;
                }
                case "layer":
                {
                    return 8;
                }
                case "lighten":
                {
                    return 9;
                }
                case "multiply":
                {
                    return 10;
                }
                case "overlay":
                {
                    return 11;
                }
                case "screen":
                {
                    return 12;
                }
                case "subtract":
                {
                    return 13;
                }
                default:
                {
                    return 0;
                    break;
                }
            }
        }// end function

        private function LayerTypeToInt(getPixels:LayerType) : int
        {
            switch(getPixels)
            {
                case LayerType.Bitmap:
                {
                    return 0;
                }
                case LayerType.Text:
                {
                    return 1;
                }
                case LayerType.Shape:
                {
                    return 2;
                }
                default:
                {
                    return 99;
                    break;
                }
            }
        }// end function

    }
}
